#pragma once
#include<iostream>
#include<string>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include"log.hpp"
#include <netinet/in.h>   // 定义了 struct sockaddr_in
#include <sys/socket.h>   // 定义 socket 相关函数和 struct sockaddr
#include <arpa/inet.h>
#include<string.h>
#include<functional>

using std::string;

//默认网络跟端口地址
const string defaultip="127.0.0.1";
uint16_t defaultport=8080;
// const int size=1024; 在log.hpp文件中已经定义了全局变量

log l;  //日志打印对象

//函数包装器
typedef std::function<string(string)> fun;

class Server
{
public:
    Server()
    :ip_(defaultip)
    ,port_(defaultport)
    ,run_("no")
    {}

    void Init()
    {
        socket_=socket(AF_INET,SOCK_DGRAM,0);
        if(socket_==-1)
        {
            l(err,"socker创建失败，返回值为%d,错误原因%s",errno,strerror(errno));
        }
        l(info,"socker创建成功");

        struct sockaddr_in local;
        memset(&local,0,sizeof(local)); //清除local中的内容

        local.sin_family=AF_INET;
        local.sin_addr.s_addr=inet_addr(ip_.c_str());
        local.sin_port=htons(port_);    //转换为网络字节序

        socklen_t socklen=sizeof(local);
        if(bind(socket_,reinterpret_cast<struct sockaddr*> (&local),socklen)==-1)
        {
            l(err,"bind绑定失败，errno:%d,strerror:%s",errno,strerror(errno));
        }
        l(info,"bind成功");
    }

    void Run(fun f)     //对代码进行分层
    {
        run_="yes";
        char bufferclient[size];

        while(true)
        {
            struct sockaddr_in client;  //存储客户端的网信息(ip + port)
            memset(bufferclient,0,sizeof(bufferclient));    //清空数据区
            socklen_t ClientLen=sizeof(client);
            
            if(recvfrom(socket_,bufferclient,sizeof(bufferclient)-1,0,reinterpret_cast<struct sockaddr*> (&client),&ClientLen)<0)    //接收udp数据，recvfrom返回值一般不会等于0
                l(err,"recvfrom创建链接失败，errno:%d,strerrnr:%s",errno,strerror(errno));
            else
                l(info,"recvfrom创建链接成功");
            
            string inf=bufferclient;
            string act=f(inf);    //代码分层具体要实现的功能

            if(sendto(socket_,act.c_str(),act.length(),0,reinterpret_cast<const struct sockaddr*> (&client),sizeof(client))==-1)
                l(err,"sendto发送失败,errno:%d,strerror:%s",errno,strerror(errno));    
            else
                l(info,"消息已成功发送出去");

            memset(bufferclient,0,sizeof(bufferclient));
        }
    }

    ~Server()
    {
        if(socket_>=0)    //关闭套接字
            close(socket_);
    }   

private:
    uint16_t port_;
    string ip_;
    int socket_;
    string run_;
};